package com.shj.em.biz.sell.service;

import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.shj.em.base.exception.BizException;
import com.shj.em.base.exception.EmCodeMsg;
import com.shj.em.biz.Constants;
import com.shj.em.biz.finance.service.PaymentService;
import com.shj.em.biz.sell.dto.OrderSearchDTO;
import com.shj.em.biz.sell.entity.Order;
import com.shj.em.biz.sell.entity.OrderItem;
import com.shj.em.biz.sell.mapper.OrderItemMapper;
import com.shj.em.biz.sell.mapper.OrderMapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;

import com.baomidou.mybatisplus.plugins.Page;

import java.math.BigDecimal;
import java.util.*;

import com.shj.em.biz.sys.service.CdService;
import com.shj.em.util.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;


/**
 * 订单信息 服务实现类
 *
 * @author Shen Huang Jian
 * @since 2018-07-09
 */
@Service
@Transactional
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    OrderItemMapper orderItemMapper;

    @Autowired
    PaymentService paymentService;

    public Page<Order> queryOrderPage(OrderSearchDTO searchDTO){
        searchDTO.setStatusType(CdService.CD_ORDER_STATUS);
        Page<Order> page = new Page<>(searchDTO.getPageNo(), searchDTO.getPageSize());
        List<Order> list = orderMapper.queryOrderPage(page, searchDTO);
        return page.setRecords(list);
    }

    public boolean isOrderNoExist(String orderNo, Long excludeId){
        Wrapper<Order> wrapper = new EntityWrapper<>();
        wrapper.eq("del_flag", 0).eq("order_no", orderNo);
        if(excludeId != null){
            wrapper.ne("id", excludeId);
        }
        List<Order> list = orderMapper.selectList(wrapper);
        return list != null && list.size() > 0;
    }

    private Order findOrderByOrderNo(String orderNo){
        Wrapper<Order> wrapper = new EntityWrapper<>();
        wrapper.eq("del_flag", 0).eq("order_no", orderNo);
        List<Order> list = orderMapper.selectList(wrapper);
        if(list == null || list.isEmpty()){
            return null;
        }else{
            return list.get(0);
        }
    }

    public long createOrder(Order order){
        if(StringUtils.isEmpty(order.getOrderNo())){
            order.setOrderNo(genOrderNo(order.getOrderDt()));
        }else {
            boolean exist = isOrderNoExist(order.getOrderNo(), null);
            if(exist){
                throw new BizException(EmCodeMsg.Order_No_Duplicate);
            }
        }
        order.setPlanOutDt(order.getRequireOutDt());
        order.setShipmentStatus(Constants.SHIPMENT_STATUS_NOT);
        orderMapper.insert(order);
        Order db = findOrderByOrderNo(order.getOrderNo());
        return db.getId();
    }

    public void updateOrder(Order order){
        //TODO 能修改金额吗？
        BigDecimal paid = paymentService.getTotalPaid(order.getId());
        if(order.getTotalAmount().compareTo(paid) < 0){
            throw new BizException(EmCodeMsg.Order_Amount_Update_Error);
        }
        orderMapper.updateById(order);
    }

    public Order copyOrder(Long id){
        Order order = orderMapper.selectById(id);
        Order newOrder = new Order();
        BeanUtils.copyProperties(order, newOrder);

        String orderNo = genOrderNoFromCopy(order.getOrderNo());
        newOrder.setOrderNo(orderNo);
        newOrder.setOrderDt(new Date());
        newOrder.setId(null);
        newOrder.setFromQuot(0);
        newOrder.setStatus(Constants.ORDER_STATUS_NO);
        newOrder.setShipmentStatus(Constants.SHIPMENT_STATUS_NOT);
        orderMapper.insert(newOrder);

        newOrder = orderMapper.findOrderByOrderNo(orderNo);

        //复制产品
        Wrapper<OrderItem> wrapper = new EntityWrapper<>();
        wrapper.eq("del_flag", 0).eq("order_id", id);
        List<OrderItem> list = orderItemMapper.selectList(wrapper);

        if(list != null && list.size() > 0){
            OrderItem tmp = null;
            for(OrderItem item : list){
                tmp = new OrderItem();
                BeanUtils.copyProperties(item, tmp);
                tmp.setId(null);
                tmp.setOrderId(newOrder.getId());
                orderItemMapper.insert(tmp);
            }
        }

        return newOrder;
    }

    public synchronized String genOrderNo(Date date){
        String prefix = DateUtils.format(date, "yyMMdd");
        List<Order> orders = orderMapper.findOrdersByDatePrefix(prefix);
        if(orders == null || orders.isEmpty()){
            return prefix + "01";
        }
        int max = 0;
        for(Order order : orders){
            boolean flag = StringUtils.isNumber(order.getOrderNo());
            if(flag){
                int no = Integer.parseInt(order.getOrderNo());
                max = max > no ? max : no;
            }else{ // 有可能只有 18061302-01, 没有 18061302， 因为被删了
                String num = order.getOrderNo().substring(0, order.getOrderNo().indexOf("-"));
                int no = Integer.parseInt(num);
                max = max > no ? max : no;
            }
        }
        max++;
        return max + "";
    }

    public String genOrderNoFromCopy(String orderNo){
        String search;
        if(orderNo.contains("-")){
            search = orderNo.split("-")[0];
        }else{
            search = orderNo;
        }
        String maxOrderNo = orderMapper.getMaxOrderNoByOrderNo(search);
        String newOrderNo;
        if(maxOrderNo.contains("-")){
            String[] arr = maxOrderNo.split("-");
            int no = Integer.parseInt(arr[1]) + 1;
            if(no < 10){
                newOrderNo = arr[0] + "-0" + no;
            }else{
                newOrderNo = arr[0] + "-" + no;
            }

        }else{
            newOrderNo = orderNo + "-01";
        }
        return newOrderNo;
    }

    public void editOutDate(Order order){
        Order db = orderMapper.selectById(order.getId());
        db.setOutDt(order.getOutDt());
        db.setVersion(db.getVersion() + 1);
        orderMapper.updateById(db);
    }

    public Map<Long, BigDecimal> getOrderAmountInYear(int year){
        String yearBegin = year + "-01-01";
        String yearEnd = year + "-12-31";
        List<Order> list = orderMapper.getOrderAmountList(yearBegin, yearEnd);
        Map<Long, BigDecimal> map = new HashMap<>();
        for(Order order : list){
            map.put(order.getId(), order.getTotalAmount());
        }
        return map;
    }

    /**
     * 返回每个月的销售总额。这个list 应该有12条记录
     * @param year
     * @return
     */
    public List<BigDecimal> getAmountPerMonthInYear(int year){
        String yearBegin = year + "-01-01";
        String yearEnd = year + "-12-31";
        List<Order> list = orderMapper.getAmountPerMonthInYear(yearBegin, yearEnd);
        List<BigDecimal> amountPerMonth = initTwelveMonth();

        for(Order order : list){
            amountPerMonth.set(order.getMonth() - 1, order.getTotalAmount());
        }

        return amountPerMonth;
    }

    private List<BigDecimal> initTwelveMonth(){
        List<BigDecimal> amountPerMonth = new ArrayList<>(12);

        //初始化为 0
        for(int i = 0; i < 12; i++){
            amountPerMonth.add(new BigDecimal(0));
        }
        return amountPerMonth;
    }

    public List<BigDecimal> getReturnAmountPerMonthInYear(int year){
        String yearBegin = year + "-01-01";
        String yearEnd = year + "-12-31";
        List<Map<String, Object>> results = orderMapper.getReturnAmountPerMonthInYear(yearBegin, yearEnd);

        List<BigDecimal> amountPerMonth = initTwelveMonth();
        for(Map<String, Object> map : results){
            amountPerMonth.set(((Integer)map.get("month"))-1, (BigDecimal)map.get("paid"));
        }
        return amountPerMonth;
    }

    public List<BigDecimal> getShouldReturnPerMonthInYear(int year){
        //orderMapper.updatePlanPayDate();
        String yearBegin = year + "-01-01";
        String yearEnd = year + "-12-31";

        List<Map<String, Object>> results = orderMapper.getShouldReturnPerMonthInYear(yearBegin, yearEnd);

        List<BigDecimal> amountPerMonth = initTwelveMonth();
        for(Map<String, Object> map : results){
            amountPerMonth.set(((Integer)map.get("month"))-1, (BigDecimal)map.get("totalAmount"));
        }
        return amountPerMonth;
    }

    public List<Order> findHasWorkHourOrdersInYear(int year){
        String yearBegin = year + "-01-01";
        String yearEnd = year + "-12-31";
        return orderMapper.findHasWorkHourOrdersInYear(yearBegin, yearEnd);
    }

    public void updateToFinish(Long orderId){
        orderMapper.updateToFinishProduce(orderId);
    }

    public void closeOrder(Long id){
        orderMapper.closeOrder(id);
    }
}
